﻿using UnityEngine;
using System.Collections;

public class AI : MonoBehaviour {

	public enum phase {draw, equip, spell, move, attack, end, wait};
	public phase myPhase;

	public bool waiting;
	public bool inFirstMovePhase;
	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
		if(waiting || GameController.gc.gameover)
			return;
		if(GameController.gc.playerOneTurn){
			myPhase = phase.wait;
			return;
		}
		else{
			//switch to draw phase
			if(myPhase==phase.wait){
				myPhase = phase.draw;
				Debug.Log ("switching to draw phase.");
			}
			//drawing happen automatically when turn ends., so move on to the next phase.
			else if(myPhase==phase.draw){
				StartCoroutine(waitForAnimations());
				Debug.Log ("switching to equip phase.");
				myPhase = phase.equip;
			}
			//equip any items you have
			else if(myPhase==phase.equip){
				Debug.Log ("in equip phase");
				//loop through the persons hand
				foreach(Card card in GameController.gc.playerTwoHand.hand){
					if(card!=null){
						Debug.Log ("card "+card.cardName+" in hand is not null");
						//if the card in the hand is of the type item.
						if(card.myType==Card.type.item){
							Debug.Log ("card "+card.cardName+" is an item");
							//calculate which creature would be best to equip the item with.
							Item item = (Item)card;
							Champion targetChampion = null;
							float hValue = -1;
							//check on each champion
							foreach(Champion champion in GameController.gc.champions){
								//make sure the champion is in play and is the AI's card
								if(champion!=null && champion.inPlay && !champion.player1Card){
									Debug.Log ("evaluating champion "+champion.cardName+" for item "+item.cardName);
									float thisHValue = item.evaluateEquippingItem(champion);//evaluateEquippingItem(champion, item);
									if(thisHValue > hValue){
										hValue = thisHValue;
										targetChampion = champion;
									}
								}
							}
							//equip the item
							if(targetChampion!=null){
								item.equip(targetChampion);
								StartCoroutine(waitForAnimations());
								return;
							}
						}
					}
				}
				myPhase = phase.spell;
			}
			//play any summoner spells worth playing
			else if(myPhase == phase.spell){
				Debug.Log ("in spell phase");
				//loop through the persons hand
				foreach(Card card in GameController.gc.playerTwoHand.hand){
					if(card!=null){
						//if the card in the hand is of the type spells.
						if(card.myType==Card.type.summonerspell){
							SummonerSpell spell = (SummonerSpell) card;
							//calculate which creature would be best to equip the item with.
							Champion targetChampion = null;
							float hValue = -1;
							foreach(Champion champion in GameController.gc.champions){
								if(champion!=null && champion.inPlay && ((spell.forAllies && !champion.player1Card) || (!spell.forAllies && champion.player1Card))){
									Debug.Log ("evaluating champion "+champion.cardName+" for summoner spell "+spell.cardName);
									float thisHValue = spell.evaluateSummonerSpell(champion);
									if(thisHValue > hValue){
										hValue = thisHValue;
										targetChampion = champion;
									}
								}
							}
							//play the spell
							if(targetChampion!=null && hValue > 0){
								spell.playSpell(targetChampion);
								StartCoroutine(waitForAnimations());
								return;
							}
						}
					}
				}
				inFirstMovePhase = true;
				myPhase = phase.move;
			}
			//perform any move actions
			else if(myPhase == phase.move){
				Debug.Log ("in move phase.");
				foreach(Champion champion in GameController.gc.champions){
					if(champion!=null && !champion.player1Card && champion.numMovesThisTurn < champion.numMoves){
						float hValue = evalulateBoardMovement(champion,0,0);
						int xValue = 0;
						int yValue = 0;
						for(int i = -1; i < 2;i++){
							for(int j = -1; j < 2;j++){
								//is this move in range
								if(i==0 || j==0 && !(i==0 && j==0)){
									Vector2 newPosition = new Vector2(champion.myGridCell.gridPosition.x + i, champion.myGridCell.gridPosition.y + j);
									//is this move valid
									if(newPosition.x <= 3 && newPosition.x >= 0 && newPosition.y <= 3 && newPosition.y >= 0 && !GameController.gc.board[(int)newPosition.x,(int)newPosition.y].hasCard){
										float thisHValue = evalulateBoardMovement(champion, i, j);
										if(thisHValue > hValue){
											xValue = (int)newPosition.x;
											yValue = (int)newPosition.y;
											hValue = thisHValue;
										}
									}
								}
							}
						}
						if(xValue != 0 || yValue !=0){
							champion.move (xValue - (int)champion.myGridCell.gridPosition.x,yValue - (int) champion.myGridCell.gridPosition.y);
							StartCoroutine(waitForAnimations());
							return;
						}
					}
				}
				if(inFirstMovePhase)
					myPhase = phase.attack;
				else
					myPhase = phase.end;
			}
			//perform any attacks
			else if(myPhase == phase.attack){
				Debug.Log ("in attack phase");
				foreach(Champion champion in GameController.gc.champions){
					if(champion!=null && !champion.player1Card && champion.numAttacksThisTurn < champion.numAttacks){
						float hValue = 0;
						float nexusHValue = 0;
						//if the players nexus can be attacked
						if(champion.myGridCell.gridPosition.x >= 4 - champion.attackRange && GameController.gc.playerOneNexus.numTurnsFortified <= 0){
							nexusHValue = evaluateAttack(champion, GameController.gc.playerOneNexus);
						}
						Champion targetChampion = null;
						foreach(Champion enemyChampion in GameController.gc.champions){
							if(enemyChampion!=null && enemyChampion.player1Card){
								float distance = Mathf.Abs(champion.myGridCell.gridPosition.x - enemyChampion.myGridCell.gridPosition.x) + Mathf.Abs(champion.myGridCell.gridPosition.y - enemyChampion.myGridCell.gridPosition.y);
								if(distance <= champion.attackRange){
									float thisHValue = evaluateAttack(champion, enemyChampion);
									if(thisHValue > hValue){
										targetChampion = enemyChampion;
										hValue = thisHValue;
									}
								}
							}
						}
						if(hValue > 0 || nexusHValue > 0){
							if(nexusHValue > hValue){
								champion.useAttack(GameController.gc.playerOneNexus);
								StartCoroutine(waitForAnimations());
								return;
							}
							else{
								champion.useAttack(targetChampion);
								Debug.Log ("Champion "+champion.cardName+" attacked "+targetChampion.cardName);
								StartCoroutine(waitForAnimations());
								return;
							}
						}
					}
				}
				inFirstMovePhase = false;
				myPhase = phase.move;
			}
			//end your turn
			else if(myPhase == phase.end){
				Debug.Log ("in end phase");
				GameController.gc.startTurn();
				myPhase = phase.wait;
			}
		}
	}
	//evaluate the board after a move is made.
	float evalulateBoardMovement(Champion champion, float x, float y){
		float hValue = 0;
		bool noChampions = true;
		foreach(Champion enemyChampion in GameController.gc.champions){
			if(enemyChampion!=null && enemyChampion.player1Card){
				noChampions = false;
				float distance = Mathf.Abs(champion.myGridCell.gridPosition.x + x - enemyChampion.myGridCell.gridPosition.x) + Mathf.Abs(champion.myGridCell.gridPosition.y + y - enemyChampion.myGridCell.gridPosition.y);
				if(distance <= (enemyChampion.attackRange + enemyChampion.numMoves)) {
					if(champion.health <= enemyChampion.attack){
						hValue -= 10;
					}
					else{
						hValue += 10;
					}
				}
				else if(distance <= champion.attackRange){
					if(enemyChampion.health <= champion.attack){
						hValue += 10;
					}
					else
						hValue-=0;
				}
				else{
					float currentDistance = Mathf.Abs(champion.myGridCell.gridPosition.x - enemyChampion.myGridCell.gridPosition.x) + Mathf.Abs(champion.myGridCell.gridPosition.y - enemyChampion.myGridCell.gridPosition.y);
					if(currentDistance > distance){
						hValue += 8;
					}
					else{
						hValue -= 5;
					}
				}
			}
		}
		if(champion.myGridCell.gridPosition.x+x==3)
			hValue += 10;
		if(champion.myGridCell.gridPosition.x+x > champion.myGridCell.gridPosition.x && noChampions){
			hValue += 100;
		}
		return hValue;
	}

	float evaluateAttack(Champion champion, bool attackingNexus){
		float hValue = 0;
		if(GameController.gc.playerOneNexus.Health - champion.attack <= 0.0f){
			hValue = 9999;
			return hValue;
		}
		return 100-(GameController.gc.playerOneNexus.Health - champion.attack);
	}
	float evaluateAttack(Champion champion, Champion enemyChampion){
		float hValue = 0;
		if(enemyChampion.health <= champion.attack){
			return 100.0f;
		}
		float possibleAdditionalAttacks = 0;
		foreach(Champion alliedChampion in GameController.gc.champions){
			if(alliedChampion!=null && !alliedChampion.player1Card && alliedChampion.name!=champion.name){
				float distance = Mathf.Abs(alliedChampion.myGridCell.gridPosition.x - enemyChampion.myGridCell.gridPosition.x) + Mathf.Abs(alliedChampion.myGridCell.gridPosition.y - enemyChampion.myGridCell.gridPosition.y);
				if(distance <= alliedChampion.attackRange){
					possibleAdditionalAttacks+=alliedChampion.attack;
				}
			}
		}
		if(enemyChampion.health <= (champion.attack + possibleAdditionalAttacks)){
			hValue = 90.0f;
		}
		else{
			hValue = enemyChampion.health - (champion.attack + possibleAdditionalAttacks/2.0f);
		}
		return hValue;
	}


	//function for evaluating the current state of the board
	float evaluateBoard(){
		float AIHValue = 0;
		float playerHValue = 0;
		//cards in hand are worth 10 points
		foreach(Card card in GameController.gc.playerOneHand.hand)
			playerHValue += 10;
		foreach(Card card in GameController.gc.playerTwoHand.hand)
			AIHValue += 10f;
		//champions gain value based on their attack, health, number of moves, number of attacks, and position relative to enemy champions.
		foreach (Champion champion in GameController.gc.champions){
			if(champion!=null){
				float championValue = 0;
				championValue += champion.attack;
				championValue += champion.health/10.0f;
				championValue += champion.numMoves;
				championValue += champion.numAttacks*5;
				foreach(Champion enemyChampion in GameController.gc.champions){
					if(enemyChampion!=null && champion.player1Card!=enemyChampion.player1Card){
						//if an enemy champion is within the attack range of the champion we are testing
						if((Mathf.Abs(champion.myGridCell.gridPosition.x - enemyChampion.myGridCell.gridPosition.x) + Mathf.Abs(champion.myGridCell.gridPosition.y - enemyChampion.myGridCell.gridPosition.y))<champion.attackRange){
							championValue+=5;
						}
					}
				}
				if(champion.player1Card)
					playerHValue += championValue;
				else
					AIHValue += championValue;
			}
		}
		return AIHValue - playerHValue;
	}

	float evaluateEquippingItem(Champion champion, Item item){
		float hValue = 0;
		hValue += item.AD * (champion.basicAbilityScalingAd + champion.ultAbilityScalingAd);
		hValue += item.AP * (champion.basicAbilityScalingAp + champion.ultAbilityScalingAp);
		hValue += item.Health + champion.maxHealth/10.0f;
		return hValue;
	}

	//wait for animations to play before making your next move
	IEnumerator waitForAnimations(){
		waiting = true;
		yield return new WaitForSeconds(GameController.gc.animationTime+.5f);
		waiting = false;
	}
}
